// https://shop64022682.taobao.com/ DIY模块地址
#include <Arduino.h>
#include "driver/timer.h" // 使用定时器所需头文件

const int ledPIN = 2; // LED物理引脚定义
static unsigned int cntTimer = 0;
// 定时器初始化函数声明，设置定时器参数，并启动定时器
void Time_Init(unsigned int usCnt);
// 设置函数，只在程序启动后运行一次
void setup() {
  pinMode(ledPIN,OUTPUT); // 将LED引脚设置为输出模式
  Time_Init(500 * 1000); // 设置定时器中断500ms响一次
}
// 循环函数，循环执行主程序
void loop() {
  // put your main code here, to run repeatedly:
}
//定时器中断回调函数,定时器中断响时，执行此函数中代码
void IRAM_ATTR timer_group0_isr(void *para){
   int timer_idx = (int) para;
    uint32_t intr_status = TIMERG0.int_st_timers.val; //获取定时器中断状态 
    if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) {
        TIMERG0.int_clr_timers.t0 = 1;  //清除中断标志
    } 
    TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN;  //再次使能alarm    
    cntTimer++;// 中断每响一次，LED切换一次亮灭状态
    digitalWrite(ledPIN, cntTimer%2);
}
// 定时器初始化函数声明，设置定时器参数，并启动定时器
void Time_Init(unsigned int usCnt) {  
	timer_config_t config;// 设置定时器初始化参数
  config.divider = 8; //分频系数
	config.counter_dir = TIMER_COUNT_UP; //计数方式为向上计数
	config.counter_en = TIMER_PAUSE; //调用timer_init函数以后不启动计数,调用timer_start时才开始计数
	config.alarm_en = TIMER_ALARM_EN; //到达计数值启动报警（计数值溢出，进入中断）
  config.auto_reload = 1; //自动重新装载预装值
  // 初始化定时器
	timer_init(TIMER_GROUP_0,TIMER_0,&config); 
	// 设置定时器预装值
	timer_set_counter_value(TIMER_GROUP_0,TIMER_0,0x00000000ULL); 
	// 设置报警阈值 usCnt[定时usCnt 微秒] (TIMER_BASE_CLK[定时器时钟/8[分频系数]/1000/1000[延时为us级别，因此/1000/1000])
	timer_set_alarm_value(TIMER_GROUP_0,TIMER_0,usCnt*(TIMER_BASE_CLK/8/1000/1000)); //TIMER_BASE_CLK 为80M
	// 定时器中断使能
	timer_enable_intr(TIMER_GROUP_0,TIMER_0);
	// 注册定时器中断函数
	timer_isr_register(TIMER_GROUP_0,TIMER_0,
			timer_group0_isr,  //定时器中断回调函数
			(void*)TIMER_0,    //传递给定时器回调函数的参数
			ESP_INTR_FLAG_IRAM, //把中断放到 IRAM 中
			NULL //调用成功以后返回中断函数的地址,一般用不到
			);
	// 启动定时器
	timer_start(TIMER_GROUP_0,TIMER_0); //开始计数
}
